/*
 *  Copyright 2009 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.mybatis.generator.codegen.mybatis3.model;

import static org.mybatis.generator.internal.util.messages.Messages.getString;

import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.FullyQualifiedTable;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.codegen.AbstractJavaGenerator;
import org.mybatis.generator.codegen.RootClassInfo;

/**
 * 
 * @author Jeff Butler
 * 
 */
public class QueryRecordGenerator extends AbstractJavaGenerator {

	public QueryRecordGenerator() {
		super();
	}

	@Override
	public List<CompilationUnit> getCompilationUnits() {
		FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();
		progressCallback.startTask(getString("Progress.8", table.toString())); //$NON-NLS-1$
		Plugin plugins = context.getPlugins();
		CommentGenerator commentGenerator = context.getCommentGenerator();

		String typeStr = introspectedTable.getBaseRecordType();
		if (typeStr != null && typeStr.lastIndexOf(".po.") != -1) {
			typeStr = typeStr.replace(".po.", ".qo.");
		}
		//typeStr += "Qo";
		typeStr = util.StringUtils.replaceLast(typeStr,"Po","Qo");
		FullyQualifiedJavaType type = new FullyQualifiedJavaType(typeStr);
		TopLevelClass topLevelClass = new TopLevelClass(type);
		topLevelClass.setVisibility(JavaVisibility.PUBLIC);
		commentGenerator.addJavaFileComment(topLevelClass);
		commentGenerator.addClassComment(topLevelClass, introspectedTable,
				true, introspectedTable.getRemarks());

		int index = typeStr.lastIndexOf(".qo.");
		typeStr = typeStr.substring(0, index + 4);

		FullyQualifiedJavaType superClass = new FullyQualifiedJavaType(typeStr
				+ "BaseQo");

		topLevelClass.setSuperClass(superClass);
		topLevelClass.addImportedType(superClass);

		List<IntrospectedColumn> introspectedColumns = getColumnsInThisClass();

		if (introspectedTable.isConstructorBased()) {
			addParameterizedConstructor(topLevelClass);

			if (!introspectedTable.isImmutable()) {
				addDefaultConstructor(topLevelClass);
			}
		}

		String rootClass = getRootClass();
		for (IntrospectedColumn introspectedColumn : introspectedColumns) {
			if (RootClassInfo.getInstance(rootClass, warnings)
					.containsProperty(introspectedColumn)) {
				continue;
			}

			Field field = getJavaBeansField(introspectedColumn);
			if (plugins.modelFieldGenerated(field, topLevelClass,
					introspectedColumn, introspectedTable,
					Plugin.ModelClassType.BASE_RECORD)) {
				topLevelClass.addField(field);
				topLevelClass.addImportedType(field.getType());
			}

			//cjianquan 2020/2/1 时间起止
			if(introspectedColumn.getJdbcTypeName().equals("TIMESTAMP") || introspectedColumn.getJdbcTypeName().equals("DATE")){
				field = getJavaBeansField4Date(introspectedColumn,"Start");
				topLevelClass.addField(field);
				topLevelClass.addImportedType(field.getType());

				field = getJavaBeansField4Date(introspectedColumn,"End");
				topLevelClass.addField(field);
				topLevelClass.addImportedType(field.getType());
			}
		}

		for (IntrospectedColumn introspectedColumn : introspectedColumns) {
			Method method = getJavaBeansGetter(introspectedColumn);
			if (plugins.modelGetterMethodGenerated(method, topLevelClass,
					introspectedColumn, introspectedTable,
					Plugin.ModelClassType.BASE_RECORD)) {
				topLevelClass.addMethod(method);
			}

			if (!introspectedTable.isImmutable()) {
				method = getJavaBeansSetter(introspectedColumn);
				if (plugins.modelSetterMethodGenerated(method, topLevelClass,
						introspectedColumn, introspectedTable,
						Plugin.ModelClassType.BASE_RECORD)) {
					topLevelClass.addMethod(method);
				}
			}

			//cjianquan 2020/2/1 判断类型是否日期，则要生成对应的Start、End属性与方法
			if(introspectedColumn.getJdbcTypeName().equals("TIMESTAMP") || introspectedColumn.getJdbcTypeName().equals("DATE")){
				method = getJavaBeansGetter4Date(introspectedColumn,"Start");
				topLevelClass.addMethod(method);
				method = getJavaBeansSetter4Date(introspectedColumn,"Start");
				topLevelClass.addMethod(method);

				method = getJavaBeansGetter4Date(introspectedColumn,"End");
				topLevelClass.addMethod(method);
				method = getJavaBeansSetter4Date(introspectedColumn,"End");
				topLevelClass.addMethod(method);
			}
		}

		//addToStringMethod(topLevelClass, introspectedTable);
		List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
		if (context.getPlugins().modelBaseRecordClassGenerated(topLevelClass,
				introspectedTable)) {
			answer.add(topLevelClass);
		}
		return answer;
	}

	/**
	 * 添加toString方法
	 * 
	 * @param topLevelClass
	 */
	protected void addToStringMethod(TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		String tableName = introspectedTable.getTableConfiguration()
				.getTableName();
		List<IntrospectedColumn> introspectedColumns = getColumnsInThisClass();

		Method method = new Method();
		method.setName("toString");
		method.setReturnType(new FullyQualifiedJavaType("String"));
		method.setVisibility(JavaVisibility.PUBLIC);
		StringBuilder sb = new StringBuilder();
		sb.append("return \"" + tableName + "{\"");
		int i = 0;
		for (IntrospectedColumn introspectedColumn : introspectedColumns) {
			String property = introspectedColumn.getJavaProperty();
			if (i == 0) {
				sb.append("+\"" + property + "["
						+ introspectedColumn.getRemarks() + "]=\"+" + property);
			} else {
				sb.append("+\"," + property + "["
						+ introspectedColumn.getRemarks() + "]=\"+" + property);
			}
			++i;
		}
		sb.append("+\"}\";");
		method.addBodyLine(sb.toString());
		method.addAnnotation("@Override");
		topLevelClass.addMethod(method);
	}

	private boolean includePrimaryKeyColumns() {
		return !introspectedTable.getRules().generatePrimaryKeyClass()
				&& introspectedTable.hasPrimaryKeyColumns();
	}

	private boolean includeBLOBColumns() {
		return !introspectedTable.getRules().generateRecordWithBLOBsClass()
				&& introspectedTable.hasBLOBColumns();
	}

	private void addParameterizedConstructor(TopLevelClass topLevelClass) {
		Method method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setConstructor(true);
		method.setName(topLevelClass.getType().getShortName());
		context.getCommentGenerator().addGeneralMethodComment(method,
				introspectedTable);

		List<IntrospectedColumn> constructorColumns = includeBLOBColumns() ? introspectedTable
				.getAllColumns() : introspectedTable.getNonBLOBColumns();

		for (IntrospectedColumn introspectedColumn : constructorColumns) {
			method.addParameter(new Parameter(introspectedColumn
					.getFullyQualifiedJavaType(), introspectedColumn
					.getJavaProperty()));
		}

		StringBuilder sb = new StringBuilder();
		if (introspectedTable.getRules().generatePrimaryKeyClass()) {
			boolean comma = false;
			sb.append("super("); //$NON-NLS-1$
			for (IntrospectedColumn introspectedColumn : introspectedTable
					.getPrimaryKeyColumns()) {
				if (comma) {
					sb.append(", "); //$NON-NLS-1$
				} else {
					comma = true;
				}
				sb.append(introspectedColumn.getJavaProperty());
			}
			sb.append(");"); //$NON-NLS-1$
			method.addBodyLine(sb.toString());
		}

		List<IntrospectedColumn> introspectedColumns = getColumnsInThisClass();

		for (IntrospectedColumn introspectedColumn : introspectedColumns) {
			sb.setLength(0);
			sb.append("this."); //$NON-NLS-1$
			sb.append(introspectedColumn.getJavaProperty());
			sb.append(" = "); //$NON-NLS-1$
			sb.append(introspectedColumn.getJavaProperty());
			sb.append(';');
			method.addBodyLine(sb.toString());
		}

		topLevelClass.addMethod(method);
	}

	private List<IntrospectedColumn> getColumnsInThisClass() {
		List<IntrospectedColumn> introspectedColumns;
		if (includePrimaryKeyColumns()) {
			if (includeBLOBColumns()) {
				introspectedColumns = introspectedTable.getAllColumns();
			} else {
				introspectedColumns = introspectedTable.getNonBLOBColumns();
			}
		} else {
			if (includeBLOBColumns()) {
				introspectedColumns = introspectedTable
						.getNonPrimaryKeyColumns();
			} else {
				introspectedColumns = introspectedTable.getBaseColumns();
			}
		}

		return introspectedColumns;
	}
}
